#include "../common_defs.h"
#include "../vm/c_vm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define int intptr_t
#define BUFFER_SIZE 4096

char* get_eval_result(char* code){
    char *buffer = NULL;
    buffer = (char *)malloc(BUFFER_SIZE);
    if(!buffer){
        perror("buffer malloc failed");
        return NULL;
    }
    memset(buffer, 0, BUFFER_SIZE);
    vm_running_env_init();
    int op, *tmp;
    int buffer_pos = 0;
    
    while (1) {
        op = *pc++;
        if (op == IMM) {
            ax = *pc++;
        }
        else if (op == LC) {
            ax = *(char *)ax;
        }
        else if (op == LI) {
            ax = *(int *)ax;
        }
        else if (op == SC) {
            ax = *(char *)*sp++ = ax;
        }
        else if (op == SI) {
            *(int *)*sp++ = ax;
        }
        else if (op == PUSH) {
            *--sp = ax;
        }
        else if (op == JMP) {
            pc = (int *)*pc;
        }
        else if (op == JZ) {
            pc = ax ? pc + 1 : (int *)*pc;
        }
        else if (op == JFZ){
            pc = ax ? (int*)*(pc + 1) : (int *)*pc;
        }
        else if (op == JNZ) {
            pc = ax ? (int *)*pc : pc + 1;
        }
        else if (op == CALL) {
            *--sp = (int)(pc+1);
            pc = (int *)*pc;
        }
        else if (op == ENT) {
            *--sp = (int)bp;
            bp = sp;
            sp = sp - *pc++;
        }
        else if (op == ADJ) {
            sp = sp + *pc++;
        }
        else if (op == LEV) {
            sp = bp;
            bp = (int *)*sp++;
            pc = (int *)*sp++;
        }
        else if (op == LEA) {
            ax = (int)(bp + *pc++);
        }
        else if (op == OR) {
            ax = *sp++ | ax;
        }
        else if (op == XOR) {
            ax = *sp++ ^ ax;
        }
        else if (op == AND) {
            ax = *sp++ & ax;
        }
        else if (op == EQ) {
            ax = *sp++ == ax;
        }
        else if (op == NE) {
            ax = *sp++ != ax;
        }
        else if (op == LT) {
            ax = *sp++ < ax;
        }
        else if (op == LE) {
            ax = *sp++ <= ax;
        }
        else if (op == GT) {
            ax = *sp++ > ax;
        }
        else if (op == GE) {
            ax = *sp++ >= ax;
        }
        else if (op == SHL) {
            ax = *sp++ << ax;
        }
        else if (op == SHR) {
            ax = *sp++ >> ax;
        }
        else if (op == ADD) {
            ax = *sp++ + ax;
        }
        else if (op == SUB) {
            ax = *sp++ - ax;
        }
        else if (op == MUL) {
            ax = *sp++ * ax;
        }
        else if (op == DIV) {
            ax = *sp++ / ax;
        }
        else if (op == MOD) {
            ax = *sp++ % ax;
        }
        else if (op == EXIT) {
            buffer_pos += snprintf(buffer + buffer_pos, BUFFER_SIZE - buffer_pos, "exit(%lld)\n", *sp);
            break;
        }
        else if (op == OPEN) {
            ax = open((char *)sp[1], (int)sp[0]);
            buffer_pos += snprintf(buffer + buffer_pos, BUFFER_SIZE - buffer_pos, "open: %lld\n", ax);
        }
        else if (op == CLOS) {
            ax = close((int)*sp);
            buffer_pos += snprintf(buffer + buffer_pos, BUFFER_SIZE - buffer_pos, "close: %lld\n", ax);
        }
        else if (op == READ) {
            ax = read((int)sp[2], (char *)sp[1], (int)*sp);
            buffer_pos += snprintf(buffer + buffer_pos, BUFFER_SIZE - buffer_pos, "read: %lld\n", ax);
        }
        else if (op == PRTF) {
            tmp = sp + pc[1];
            // 创建临时缓冲区来捕获printf的输出
            char printf_buffer[1024] = {0};
            int printf_len = snprintf(printf_buffer, sizeof(printf_buffer), (char *)tmp[-1], tmp[-2], tmp[-3], tmp[-4], tmp[-5], tmp[-6]);
            ax = printf_len;
            
            // 将printf的原始输出添加到结果缓冲区
            buffer_pos += snprintf(buffer + buffer_pos, BUFFER_SIZE - buffer_pos, "%s", printf_buffer);
        }
        else if (op == SCANF) {
            tmp = sp + pc[1];
            ax = scanf((char *)tmp[-1], tmp[-2], tmp[-3], tmp[-4], tmp[-5], tmp[-6]);
        }
        else if (op == MALC) {
            ax = (int)malloc(*sp);
        }
        else if (op == MSET) {
            ax = (int)memset((char *)sp[2], sp[1], *sp);
        }
        else if (op == MCMP) {
            ax = memcmp((char *)sp[2], (char *)sp[1], *sp);
        }
        else if (op == FREE) {
            free((char *)*sp);
        }
        else {
            printf("unknown instruction:%lld\n", op);
            buffer_pos += snprintf(buffer + buffer_pos, BUFFER_SIZE - buffer_pos, "unknown instruction:%lld\n", op);
            break;
        }
    }
    
    return buffer;
}

void free_result(char* result){
    if(result){
        free(result);
    }
}